home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / program / freeli22.zip / 386LIB2.ASX < prev    next >
Text File  |  1996-09-01  |  73KB  |  2,724 lines

  1. ~~~C_STR1
  2. Ideal
  3.  
  4. Public      strlen,strcpy,strcat,strcmp
  5.  
  6. Model Tiny
  7. CodeSeg
  8. P386
  9.  
  10. ;****************** strlen() -- Get length of string
  11. ;int strlen(char *strp);
  12.  
  13. strp        equ bp+4
  14.  
  15. Proc        strlen
  16.  
  17.             push bp                 ;Set up stack frame
  18.             mov bp,sp
  19.             push si                 ;Save SI
  20.  
  21.             mov si,[strp]           ;SI = string pointer
  22.  
  23. p1_loop:    lodsb                   ;Load char
  24.             test al,al              ;Loop while not zero
  25.             jnz p1_loop
  26.  
  27.             sub si,[strp]           ;AX = length
  28.             dec si
  29.             xchg ax,si
  30.  
  31.             pop si                  ;Restore SI
  32.             pop bp                  ;Delete stack frame
  33.             ret 2                   ;Return
  34.  
  35. EndP        strlen
  36.  
  37. ;****************** strcpy() -- Copy a string
  38. ;void strcpy(char *str1, char *str2);
  39.  
  40. str1        equ bp+6
  41. str2        equ bp+4
  42.  
  43. Proc        strcpy
  44.  
  45.             push bp                 ;Set up stack frame
  46.             mov bp,sp
  47.             pusha                   ;Save all registers
  48.  
  49.             mov si,[str2]           ;SI = source
  50.             mov di,[str1]           ;DI = destination
  51.  
  52. p2_loop:    lodsb                   ;Load char
  53.             mov [di],al             ;Store char
  54.             inc di
  55.             test al,al              ;Loop while not zero
  56.             jnz p2_loop
  57.  
  58.             popa                    ;Restore registers
  59.             pop bp                  ;Delete stack frame
  60.             ret 4                   ;Return
  61.  
  62. EndP        strcpy
  63.  
  64. ;****************** strcat() -- Concatenate strings
  65. ;void strcat(char *str1, char *str2);
  66.  
  67. str1        equ bp+6
  68. str2        equ bp+4
  69.  
  70. Proc        strcat
  71.  
  72.             push bp                 ;Set up stack frame
  73.             mov bp,sp
  74.             pusha                   ;Save all registers
  75.  
  76.             mov si,[str1]           ;SI = destination
  77.  
  78. p3_cloop:   lodsb                   ;Load char
  79.             test al,al              ;Loop while not zero
  80.             jnz p3_cloop
  81.  
  82.             mov di,si               ;DI = destination
  83.             mov si,[str2]           ;SI = source
  84.             dec di
  85.  
  86. p3_loop:    lodsb                   ;Load char
  87.             mov [di],al             ;Store char
  88.             inc di
  89.             test al,al              ;Loop while not zero
  90.             jnz p3_loop
  91.  
  92.             popa                    ;Restore registers
  93.             pop bp                  ;Delete stack frame
  94.             ret 4                   ;Return
  95.  
  96. EndP        strcat
  97.  
  98. ;****************** strcmp() -- Compare strings
  99. ;void strcmp(char *str1, char *str2);
  100.  
  101. str1        equ bp+6
  102. str2        equ bp+4
  103.  
  104. Proc        strcmp
  105.  
  106.             push bp                 ;Set up stack frame
  107.             mov bp,sp
  108.             push si di              ;Save registers
  109.  
  110.             mov si,[str1]           ;SI = source
  111.             mov di,[str2]           ;DI = destination
  112.  
  113. p4_loop:    lodsb                   ;Load char 1
  114.             mov ah,[di]             ;Load char 2
  115.             inc di
  116.             cmp al,ah               ;Not equal?
  117.             jne p4_nope
  118.             test al,al              ;Loop while not zero
  119.             jnz p4_loop
  120.  
  121.             xor ax,ax               ;Equal, return 0
  122. p4_done:    pop di si               ;Restore registers
  123.             pop bp                  ;Delete stack frame
  124.             ret 4                   ;Return
  125.  
  126. p4_nope:    sub al,ah               ;Not equal, return difference
  127.             cbw                     ;in first unequal position
  128.             jmp p4_done
  129.  
  130. EndP        strcmp
  131.  
  132. End
  133.  
  134. ~~~C_STR2
  135. Ideal
  136.  
  137. Extrn       strlen:near
  138. Public      strchr,strstr
  139.  
  140. Model Tiny
  141. CodeSeg
  142. P386
  143.  
  144. ;****************** strchr() -- Search string for char
  145. ;int strchr(char *strp, int chr);
  146.  
  147. strp        equ bp+6
  148. chr         equ bp+4
  149.  
  150. Proc        strchr
  151.  
  152.             push bp                 ;Set up stack frame
  153.             mov bp,sp
  154.             push si                 ;Save SI
  155.  
  156.             mov si,[strp]           ;SI = string pointer
  157.             mov ah,[chr]            ;AH = char
  158.  
  159. p1_loop:    lodsb                   ;Load char
  160.             test al,al              ;Null, not found
  161.             jz p1_nope
  162.             cmp al,ah               ;Loop while not equal
  163.             jne p1_loop
  164.  
  165.             sub si,[strp]           ;AX = position of char
  166.             dec si
  167.             xchg ax,si
  168.  
  169. p1_done:    pop si                  ;Restore SI
  170.             pop bp                  ;Delete stack frame
  171.             ret 4                   ;Return
  172.  
  173. p1_nope:    mov ax,-1               ;Not found, return -1
  174.             jmp p1_done
  175.  
  176. EndP        strchr
  177.  
  178. ;****************** strstr() -- Search string for substring
  179. ;int strstr(char *strp, char *subp);
  180.  
  181. strp        equ bp+6
  182. subp        equ bp+4
  183.  
  184. Proc        strstr
  185.  
  186.             push bp                 ;Set up stack frame
  187.             mov bp,sp
  188.             pusha                   ;Save all registers
  189.             push es
  190.  
  191.             push ds                 ;ES = DS
  192.             pop es
  193.  
  194.             mov si,[strp]           ;SI = string pointer
  195.             mov bx,[subp]           ;BX = substring pointer
  196.             push bx                 ;Get length of substring
  197.             call strlen             ;into DX
  198.             xchg dx,ax
  199.             mov ah,[bx]             ;AH = first char
  200.  
  201. p3_loop:    lodsb                   ;Load char
  202.             test al,al              ;Null, not found
  203.             jz p3_nope
  204.             cmp al,ah               ;Loop while not equal
  205.             jne p3_loop
  206.  
  207.             mov cx,dx               ;CX = length
  208.             mov di,bx               ;DI = substring
  209.             push si                 ;Save SI
  210.             dec si                  ;Push back char
  211.             repe cmpsb              ;Compare strings
  212.             pop si                  ;Restore SI
  213.             jne p3_loop             ;Loop if not equal
  214.  
  215.             sub si,[strp]           ;AX = position of char
  216.             dec si
  217.  
  218. p3_done:    mov [bp-2],si           ;Change pushed AX
  219.             pop es                  ;Restore registers
  220.             popa
  221.             pop bp                  ;Delete stack frame
  222.             ret 4                   ;Return
  223.  
  224. p3_nope:    mov si,-1               ;Not found, return -1
  225.             jmp p3_done
  226.  
  227. EndP        strstr
  228.  
  229. End
  230.  
  231. ~~~C_STR3
  232. Ideal
  233.  
  234. Public      stricmp,strlwr,strupr
  235.  
  236. Model Tiny
  237. CodeSeg
  238. P386
  239.  
  240. ;****************** stricmp() -- Compare strings, case insensitive
  241. ;void stricmp(char *str1, char *str2);
  242.  
  243. str1        equ bp+6
  244. str2        equ bp+4
  245.  
  246. Proc        stricmp
  247.  
  248.             push bp                 ;Set up stack frame
  249.             mov bp,sp
  250.             push si di              ;Save registers
  251.  
  252.             mov si,[str1]           ;SI = source
  253.             mov di,[str2]           ;DI = destination
  254.  
  255. p1_loop:    lodsb                   ;Load char 1
  256.             mov ah,[di]             ;Load char 2
  257.             inc di
  258.  
  259.             cmp al,'a'              ;Convert AL to uppercase
  260.             jb p1_setAH
  261.             cmp al,'z'
  262.             ja p1_setAH
  263.             sub al,20h
  264.  
  265. p1_setAH:   cmp ah,'a'              ;Convert AH to uppercase
  266.             jb p1_comp
  267.             cmp ah,'z'
  268.             ja p1_comp
  269.             sub ah,20h
  270.  
  271. p1_comp:    cmp al,ah               ;Equal?
  272.             jne p1_nope
  273.             test al,al              ;Loop while not zero
  274.             jnz p1_loop
  275.  
  276.             inc ax                  ;Equal, return 1
  277.  
  278. p1_done:    pop di si               ;Restore registers
  279.             pop bp                  ;Delete stack frame
  280.             ret 4                   ;Return
  281.  
  282. p1_nope:    xor ax,ax               ;Not equal, return 0
  283.             jmp p1_done
  284.  
  285. EndP        stricmp
  286.  
  287. ;****************** strlwr() -- Convert string to lowercase
  288. ;int strlwr(char *strp);
  289.  
  290. strp        equ bp+4
  291.  
  292. Proc        strlwr
  293.  
  294.             push bp                 ;Set up stack frame
  295.             mov bp,sp
  296.             pusha                   ;Save registers
  297.  
  298.             mov si,[strp]           ;SI = string pointer
  299.  
  300. p2_loop:    lodsb                   ;Load char
  301.             test al,al              ;Check for null
  302.             jz p2_done
  303.             cmp al,'A'              ;Check for uppercase
  304.             jb p2_loop
  305.             cmp al,'Z'
  306.             ja p2_loop
  307.             add al,20h              ;Convert to lowercase
  308.             mov [si-1],al           ;Store char
  309.             jmp p2_loop
  310.  
  311. p2_done:    popa                    ;Restore registers
  312.             pop bp                  ;Delete stack frame
  313.             ret 2                   ;Return
  314.  
  315. EndP        strlwr
  316.  
  317. ;****************** strupr() -- Convert string to uppercase
  318. ;int strupr(char *strp);
  319.  
  320. strp        equ bp+4
  321.  
  322. Proc        strupr
  323.  
  324.             push bp                 ;Set up stack frame
  325.             mov bp,sp
  326.             pusha                   ;Save registers
  327.  
  328.             mov si,[strp]           ;SI = string pointer
  329.  
  330. p3_loop:    lodsb                   ;Load char
  331.             test al,al              ;Check for null
  332.             jz p3_done
  333.             cmp al,'a'              ;Check for lowercase
  334.             jb p3_loop
  335.             cmp al,'z'
  336.             ja p3_loop
  337.             sub al,20h              ;Convert to uppercase
  338.             mov [si-1],al           ;Store char
  339.             jmp p3_loop
  340.  
  341. p3_done:    popa                    ;Restore registers
  342.             pop bp                  ;Delete stack frame
  343.             ret 2                   ;Return
  344.  
  345. EndP        strupr
  346.  
  347. End
  348.  
  349. ~~~C_STR4
  350. Ideal
  351.  
  352. Public      strrtrim,strltrim
  353.  
  354. Model Tiny
  355. CodeSeg
  356. P386
  357.  
  358. ;****************** strrtrim() -- Trim trailing spaces off a string
  359. ;int strrtrim(char *strp);
  360.  
  361. strp        equ bp+4
  362.  
  363. Proc        strrtrim
  364.  
  365.             push bp                 ;Set up stack frame
  366.             mov bp,sp
  367.             pusha                   ;Save registers
  368.  
  369.             mov si,[strp]           ;SI = string pointer
  370.             mov di,si               ;DI = SI
  371.  
  372. p1_loop:    lodsb                   ;Load char
  373.             test al,al              ;Check for null
  374.             jz p1_done
  375.             cmp al,' '              ;Check for space
  376.             je p1_loop
  377.             mov di,si               ;Set pointer
  378.             jmp p1_loop
  379.  
  380. p1_done:    mov [byte di+1],al      ;Terminate string
  381.             popa                    ;Restore registers
  382.             pop bp                  ;Delete stack frame
  383.             ret 2                   ;Return
  384.  
  385. EndP        strrtrim
  386.  
  387. ;****************** strltrim() -- Trim leading spaces off a string
  388. ;int strltrim(char *strp);
  389.  
  390. strp        equ bp+4
  391.  
  392. Proc        strltrim
  393.  
  394.             push bp                 ;Set up stack frame
  395.             mov bp,sp
  396.             pusha                   ;Save registers
  397.  
  398.             mov si,[strp]           ;SI, DI = string pointer
  399.             mov di,si
  400.  
  401. p2_loop:    lodsb                   ;Load char
  402.             test al,al              ;Check for null
  403.             jz p2_cont
  404.             cmp al,' '              ;Loop while space
  405.             je p2_loop
  406.  
  407. p2_cont:    dec si                  ;Move back one char
  408.             cmp si,di               ;No spaces, quit
  409.             je p2_done
  410.  
  411. p2_cloop:   lodsb                   ;Shift the string over
  412.             mov [di],al
  413.             inc di
  414.             test al,al
  415.             jnz p2_cloop
  416.  
  417. p2_done:    popa                    ;Restore registers
  418.             pop bp                  ;Delete stack frame
  419.             ret 2                   ;Return
  420.  
  421. EndP        strltrim
  422.  
  423. End
  424.  
  425. ~~~C_MEM1
  426. Ideal
  427.  
  428. Public      memcpy,memset
  429.  
  430. Model Tiny
  431. CodeSeg
  432. P386
  433.  
  434. ;****************** memcpy() -- Copy memory block
  435. ;void memcpy(void *p1, void *p2, int nbytes);
  436.  
  437. p1          equ bp+8
  438. p2          equ bp+6
  439. nbytes      equ bp+4
  440.  
  441. Proc        memcpy
  442.  
  443.             push bp                 ;Set up stack frame
  444.             mov bp,sp
  445.             push es                 ;Save registers
  446.             pusha
  447.  
  448.             push ds                 ;ES = DS
  449.             pop es
  450.  
  451.             mov si,[p2]             ;SI = source
  452.             mov di,[p1]             ;DI = destination
  453.             mov cx,[nbytes]         ;CX = count
  454.  
  455.             cmp di,si               ;Make forward moves
  456.             jb p1_go                ;in reverse
  457.             je p1_done
  458.  
  459.             std                     ;Set direction flag
  460.             add si,cx               ;Move offsets to end
  461.             add di,cx
  462.             dec si
  463.             dec di
  464.  
  465. p1_go:      rep movsb               ;Copy memory
  466.  
  467. p1_done:    cld                     ;Clear direction flag
  468.             popa                    ;Restore registers
  469.             pop es
  470.             pop bp                  ;Delete stack frame
  471.             ret 6                   ;Return
  472.  
  473. EndP        memcpy
  474.  
  475. ;****************** memset() -- Set memory block
  476. ;void memset(void *ptr, int nbytes, int chr);
  477.  
  478. ptr         equ bp+8
  479. nbytes      equ bp+6
  480. chr         equ bp+4
  481.  
  482. Proc        memset
  483.  
  484.             push bp                 ;Set up stack frame
  485.             mov bp,sp
  486.             push es                 ;Save registers
  487.             pusha
  488.  
  489.             push ds                 ;ES = DS
  490.             pop es
  491.  
  492.             mov di,[ptr]            ;DI = block
  493.             mov cx,[nbytes]         ;CX = count
  494.             mov al,[chr]            ;AL = char
  495.             rep stosb               ;Set memory
  496.  
  497.             popa                    ;Restore registers
  498.             pop es
  499.             pop bp                  ;Delete stack frame
  500.             ret 6                   ;Return
  501.  
  502. EndP        memset
  503.  
  504. End
  505.  
  506. ~~~C_MEM2
  507. Ideal
  508.  
  509. Public      memcmp,memchr
  510.  
  511. Model Tiny
  512. CodeSeg
  513. P386
  514.  
  515. ;****************** memcmp() -- Compare memory blocks
  516. ;void memcmp(void *p1, void *p2, int nbytes);
  517.  
  518. p1          equ bp+8
  519. p2          equ bp+6
  520. nbytes      equ bp+4
  521.  
  522. Proc        memcmp
  523.  
  524.             push bp                 ;Set up stack frame
  525.             mov bp,sp
  526.             push es                 ;Save registers
  527.             push cx si di
  528.  
  529.             push ds                 ;ES = DS
  530.             pop es
  531.  
  532.             mov si,[p2]             ;SI = source
  533.             mov di,[p1]             ;DI = destination
  534.             mov cx,[nbytes]         ;CX = count
  535.             repe cmpsb              ;Compare memory
  536.  
  537.             mov ax,1                ;Assume equal
  538.             je p1_done              ;Jump if equal
  539.  
  540.             xor ax,ax               ;Not equal, return 0
  541.  
  542. p1_done:    pop di si cx            ;Restore registers
  543.             pop es
  544.             pop bp                  ;Delete stack frame
  545.             ret 6                   ;Return
  546.  
  547. EndP        memcmp
  548.  
  549. ;****************** memchr() -- Scan memory for char
  550. ;void memchr(void *ptr, int nbytes, int chr);
  551.  
  552. ptr         equ bp+8
  553. nbytes      equ bp+6
  554. chr         equ bp+4
  555.  
  556. Proc        memchr
  557.  
  558.             push bp                 ;Set up stack frame
  559.             mov bp,sp
  560.             push es                 ;Save registers
  561.             push cx si di
  562.  
  563.             push ds                 ;ES = DS
  564.             pop es
  565.  
  566.             mov di,[ptr]            ;DI = block
  567.             mov cx,[nbytes]         ;CX = count
  568.             mov al,[chr]            ;AL = char
  569.             repne scasb             ;Scan memory
  570.             jne p2_nope             ;Jump if not found
  571.  
  572.             sub di,[ptr]            ;AX = position of char
  573.             dec di
  574.             xchg ax,di
  575.  
  576. p2_done:    pop di si cx            ;Restore registers
  577.             pop es
  578.             pop bp                  ;Delete stack frame
  579.             ret 6                   ;Return
  580.  
  581. p2_nope:    mov ax,-1               ;Not found, return -1
  582.             jmp p2_done
  583.  
  584. EndP        memchr
  585.  
  586. End
  587.  
  588. ~~~C_ISRCH
  589. Ideal
  590.  
  591. Public      isearch
  592.  
  593. Model Tiny
  594. P386
  595. CodeSeg
  596.  
  597. ;****************** isearch() -- Search a sorted array of integers
  598. ;int isearch(int *ary, int size, int elem);
  599.  
  600. ary         equ bp+8
  601. size        equ bp+6
  602. elem        equ bp+4
  603.  
  604. Proc        isearch
  605.  
  606.             push bp                 ;Set up stack frame
  607.             mov bp,sp
  608.             push bx cx dx si di     ;Save registers
  609.  
  610.             mov bx,[ary]            ;BX = array
  611.             xor cx,cx               ;CX = lower limit
  612.             mov dx,[size]           ;DX = upper limit
  613.             dec dx
  614.  
  615. p1_loop:    mov si,cx               ;SI = middle element
  616.             add si,dx
  617.             shr si,1
  618.             add si,si
  619.             mov ax,[bx+si]          ;Get element
  620.             shr si,1                ;Fix SI
  621.             cmp ax,[elem]           ;Check element
  622.             je p1_found             ;Equal?
  623.             jl p1_less              ;Too low?
  624.  
  625. p1_greater: mov di,si               ;Set first half
  626.             mov si,cx
  627.             jmp p1_cont
  628.  
  629. p1_less:    mov di,dx               ;Set second half
  630.             inc si
  631.  
  632. p1_cont:    cmp cx,dx               ;Min = Max, done
  633.             je p1_nope
  634.             mov cx,si               ;Set limits
  635.             mov dx,di
  636.             jmp p1_loop             ;Loop back
  637.  
  638. p1_found:   xchg ax,si              ;AX = result
  639.  
  640. p1_done:    pop di si dx cx bx      ;Restore registers
  641.             pop bp                  ;Delete stack frame
  642.             ret 6                   ;Return
  643.  
  644. p1_nope:    mov ax,-1               ;Not found, return -1
  645.             jmp p1_done
  646.  
  647. EndP        isearch
  648.  
  649. End
  650.  
  651. ~~~C_LSRCH
  652. Ideal
  653.  
  654. Public      lsearch
  655.  
  656. Model Tiny
  657. P386
  658. CodeSeg
  659.  
  660. ;****************** lsearch() -- Search a sorted array of longs
  661. ;int lsearch(long *ary, int size, long elem);
  662.  
  663. ary         equ bp+10
  664. size        equ bp+8
  665. elem        equ bp+4
  666.  
  667. Proc        lsearch
  668.  
  669.             push bp                 ;Set up stack frame
  670.             mov bp,sp
  671.             push es                 ;Save registers
  672.             pushad
  673.  
  674.             mov bx,[ary]            ;BX = array
  675.             xor cx,cx               ;CX = lower limit
  676.             mov dx,[size]           ;DX = upper limit
  677.             dec dx
  678.  
  679. p1_loop:    mov si,cx               ;SI = middle element
  680.             add si,dx
  681.             shr si,1
  682.             shl si,2
  683.             mov eax,[bx+si]         ;Get element
  684.             shr si,2                ;Fix SI
  685.             cmp eax,[elem]          ;Check element
  686.             je p1_done              ;Equal?
  687.             jl p1_less              ;Too low?
  688.  
  689. p1_greater: mov di,si               ;Set first half
  690.             mov si,cx
  691.             jmp p1_cont
  692.  
  693. p1_less:    mov di,dx               ;Set second half
  694.             inc si
  695.  
  696. p1_cont:    cmp cx,dx               ;Min = Max, done
  697.             je p1_nope
  698.             mov cx,si               ;Set limits
  699.             mov dx,di
  700.             jmp p1_loop             ;Loop back
  701.  
  702. p1_done:    mov es,si               ;ES = result
  703.             popad                   ;Restore registers
  704.             mov ax,es               ;AX = result
  705.             pop es                  ;Restore ES
  706.             pop bp                  ;Delete stack frame
  707.             ret 8                   ;Return
  708.  
  709. p1_nope:    mov si,-1               ;Not found, return -1
  710.             jmp p1_done
  711.  
  712. EndP        lsearch
  713.  
  714. End
  715.  
  716. ~~~C_XSRCH
  717. Ideal
  718.  
  719. Public      xsearch
  720.  
  721. Model Tiny
  722. P386
  723. CodeSeg
  724.  
  725. ;****************** xsearch() -- Search sorted array, generalized
  726. ;int xsearch(void **ary, int size, void *elem, void *func);
  727.  
  728. ary         equ bp+10
  729. size        equ bp+8
  730. elem        equ bp+6
  731. func        equ bp+4
  732.  
  733. Proc        xsearch
  734.  
  735.             push bp                 ;Set up stack frame
  736.             mov bp,sp
  737.             push bx cx dx si di     ;Save registers
  738.  
  739.             mov bx,[ary]            ;BX = array
  740.             xor cx,cx               ;CX = lower limit
  741.             mov dx,[size]           ;DX = upper limit
  742.             dec dx
  743.  
  744. p3_loop:    mov si,cx               ;SI = middle element
  745.             add si,dx
  746.             shr si,1
  747.             add si,si
  748.             mov ax,[bx+si]          ;Get element
  749.             shr si,1                ;Fix SI
  750.             push ax [word elem]     ;Check element
  751.             call [word func]
  752.             test ax,ax
  753.             je p3_found             ;Equal?
  754.             jl p3_less              ;Too low?
  755.  
  756. p3_greater: mov di,si               ;Set first half
  757.             mov si,cx
  758.             jmp p3_cont
  759.  
  760. p3_less:    mov di,dx               ;Set second half
  761.             inc si
  762.  
  763. p3_cont:    cmp cx,dx               ;Min = Max, done
  764.             je p3_nope
  765.             mov cx,si               ;Set limits
  766.             mov dx,di
  767.             jmp p3_loop             ;Loop back
  768.  
  769. p3_found:   xchg ax,si              ;AX = result
  770.  
  771. p3_done:    pop di si dx cx bx      ;Restore registers
  772.             pop bp                  ;Delete stack frame
  773.             ret 8                   ;Return
  774.  
  775. p3_nope:    mov ax,-1               ;Not found, return -1
  776.             jmp p3_done
  777.  
  778. EndP        xsearch
  779.  
  780. End
  781.  
  782. ~~~C_SSRCH
  783. Ideal
  784.  
  785. Extrn       strcmp:near
  786. Public      ssearch
  787.  
  788. Model Tiny
  789. P386
  790. CodeSeg
  791.  
  792. ;****************** ssearch() -- Search a sorted array of strings
  793. ;int ssearch(char **ary, int size, char *elem);
  794.  
  795. ary         equ bp+8
  796. size        equ bp+6
  797. elem        equ bp+4
  798.  
  799. Proc        ssearch
  800.  
  801.             push bp                 ;Set up stack frame
  802.             mov bp,sp
  803.             push bx cx dx si di     ;Save registers
  804.  
  805.             mov bx,[ary]            ;BX = array
  806.             xor cx,cx               ;CX = lower limit
  807.             mov dx,[size]           ;DX = upper limit
  808.             dec dx
  809.  
  810. p1_loop:    mov si,cx               ;SI = middle element
  811.             add si,dx
  812.             shr si,1
  813.             add si,si
  814.             mov ax,[bx+si]          ;Get element
  815.             shr si,1                ;Fix SI
  816.             push ax [word elem]     ;Check element
  817.             call strcmp
  818.             test ax,ax
  819.             je p1_found             ;Equal?
  820.             jl p1_less              ;Too low?
  821.  
  822. p1_greater: mov di,si               ;Set first half
  823.             mov si,cx
  824.             jmp p1_cont
  825.  
  826. p1_less:    mov di,dx               ;Set second half
  827.             inc si
  828.  
  829. p1_cont:    cmp cx,dx               ;Min = Max, done
  830.             je p1_nope
  831.             mov cx,si               ;Set limits
  832.             mov dx,di
  833.             dec di
  834.             jmp p1_loop             ;Loop back
  835.  
  836. p1_found:   xchg ax,si              ;AX = result
  837.  
  838. p1_done:    pop di si dx cx bx      ;Restore registers
  839.             pop bp                  ;Delete stack frame
  840.             ret 6                   ;Return
  841.  
  842. p1_nope:    mov ax,-1               ;Not found, return -1
  843.             jmp p1_done
  844.  
  845. EndP        ssearch
  846.  
  847. End
  848.  
  849. ~~~C_ISORT
  850. Ideal
  851.  
  852. Public      isort
  853.  
  854. Model Tiny
  855. P386
  856. CodeSeg
  857.  
  858. ;****************** isort() -- Sort an array of integers
  859. ;void isort(int *ary, int size);
  860.  
  861. ary         equ bp+6
  862. max         equ bp+4
  863.  
  864. Proc        isort
  865.  
  866.             push bp                 ;Set up stack frame
  867.             mov bp,sp
  868.             pusha                   ;Save all registers
  869.  
  870.             mov bx,[ary]            ;Call recursive routine
  871.             xor cx,cx
  872.             mov dx,[max]
  873.             dec dx
  874.             add dx,dx
  875.             call p1_qsort
  876.  
  877.             popa                    ;Restore registers
  878.             pop bp                  ;Delete stack frame
  879.             ret 4                   ;Return
  880.  
  881. p1_qsort:   cmp cx,dx               ;One element, return
  882.             je p1_ret
  883.             pusha
  884.  
  885.             mov ax,dx               ;Two elements, sort them
  886.             sub ax,cx
  887.             cmp ax,2
  888.             jne p1_cont
  889.  
  890.             mov si,cx               ;SI, DI = low, high
  891.             mov di,dx
  892.  
  893.             mov ax,[bx+si]          ;Check them
  894.             cmp ax,[bx+di]
  895.             jle p1_done
  896.  
  897.             xchg ax,[bx+di]         ;Switch them
  898.             mov [bx+si],ax
  899.             jmp p1_done
  900.  
  901. p1_cont:    mov si,cx               ;AX = middle element
  902.             add si,dx
  903.             shr si,2
  904.             add si,si
  905.             mov ax,[bx+si]
  906.  
  907.             mov si,cx               ;SI = low, DI = high
  908.             mov di,dx
  909.  
  910. p1_loop:    cmp si,dx               ;While [BX+SI] < AX and
  911.             jge p1_loop2            ; SI < DX, advance SI
  912.             cmp ax,[bx+si]
  913.             jle p1_loop2
  914.             add si,2
  915.             jmp p1_loop
  916.  
  917. p1_loop2:   cmp di,cx               ;While [BX+DI] > AX and
  918.             jle p1_cont2            ; DI > CX, advance DI
  919.             cmp ax,[bx+di]
  920.             jge p1_cont2
  921.             sub di,2
  922.             jmp p1_loop2
  923.  
  924. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  925.             jge p1_rec
  926.  
  927.             push [word bx+si]       ;Swap elements
  928.             push [word bx+di]
  929.             pop [word bx+si]
  930.             pop [word bx+di]
  931.             add si,2                ;Advance SI, DI
  932.             sub di,2
  933.  
  934.             jmp p1_loop             ;Loop back
  935.  
  936. p1_rec:     cmp cx,si               ;If first half isn't empty,
  937.             je p1_skip1             ;recurse to sort it
  938.             xchg dx,di
  939.             call p1_qsort
  940.             xchg dx,di
  941.  
  942. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  943.             je p1_done              ;recurse to sort it
  944.             xchg cx,si
  945.             call p1_qsort
  946.             xchg cx,si
  947.  
  948. p1_done:    popa                    ;Restore registers
  949. p1_ret:     ret                     ;Return
  950.  
  951. EndP        isort
  952.  
  953. End
  954.  
  955. ~~~C_LSORT
  956. Ideal
  957.  
  958. Public      lsort
  959.  
  960. Model Tiny
  961. P386
  962. CodeSeg
  963.  
  964. ;****************** lsort() -- Sort an array of longs
  965. ;void lsort(long *ary, int size);
  966.  
  967. ary         equ bp+6
  968. max         equ bp+4
  969. num         equ bp-4
  970.  
  971. Proc        lsort
  972.  
  973.             push bp                 ;Set up stack frame
  974.             mov bp,sp
  975.             pushad                  ;Save all registers
  976.  
  977.             mov bx,[ary]            ;Call recursive routine
  978.             xor cx,cx
  979.             mov dx,[max]
  980.             dec dx
  981.             shl dx,2
  982.             call p1_qsort
  983.  
  984.             popad                   ;Restore registers
  985.             pop bp                  ;Delete stack frame
  986.             ret 4                   ;Return
  987.  
  988. p1_qsort:   cmp cx,dx               ;One element, return
  989.             je p1_ret
  990.             pusha
  991.  
  992.             mov ax,dx               ;Two elements, sort them
  993.             sub ax,cx
  994.             cmp ax,4
  995.             jne p1_cont
  996.  
  997.             mov si,cx               ;SI, DI = low, high
  998.             mov di,dx
  999.  
  1000.             mov eax,[bx+si]         ;Check them
  1001.             cmp eax,[bx+di]
  1002.             jle p1_done
  1003.  
  1004.             xchg eax,[bx+di]        ;Switch them
  1005.             mov [bx+si],eax
  1006.             jmp p1_done
  1007.  
  1008. p1_cont:    mov si,cx               ;AX = middle element
  1009.             add si,dx
  1010.             shr si,3
  1011.             shl si,2
  1012.             mov eax,[bx+si]
  1013.  
  1014.             mov si,cx               ;SI = low, DI = high
  1015.             mov di,dx
  1016.  
  1017. p1_loop:    cmp si,dx               ;While [BX+SI] < EAX and
  1018.             jge p1_loop2            ; SI < DX, advance SI
  1019.             cmp eax,[bx+si]
  1020.             jle p1_loop2
  1021.             add si,4
  1022.             jmp p1_loop
  1023.  
  1024. p1_loop2:   cmp di,cx               ;While [BX+DI] > EAX and
  1025.             jle p1_cont2            ; DI > CX, advance DI
  1026.             cmp eax,[bx+di]
  1027.             jge p1_cont2
  1028.             sub di,4
  1029.             jmp p1_loop2
  1030.  
  1031. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  1032.             jge p1_rec
  1033.  
  1034.             push [dword bx+si]      ;Swap elements
  1035.             push [dword bx+di]
  1036.             pop [dword bx+si]
  1037.             pop [dword bx+di]
  1038.             add si,4                ;Advance SI, DI
  1039.             sub di,4
  1040.  
  1041.             jmp p1_loop             ;Loop back
  1042.  
  1043. p1_rec:     cmp cx,si               ;If first half isn't empty,
  1044.             je p1_skip1             ;recurse to sort it
  1045.             xchg dx,di
  1046.             call p1_qsort
  1047.             xchg dx,di
  1048.  
  1049. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  1050.             je p1_done              ;recurse to sort it
  1051.             xchg cx,si
  1052.             call p1_qsort
  1053.             xchg cx,si
  1054.  
  1055. p1_done:    popa                    ;Restore registers
  1056. p1_ret:     ret                     ;Return
  1057.  
  1058. EndP        lsort
  1059.  
  1060. End
  1061.  
  1062. ~~~C_SSORT
  1063. Ideal
  1064.  
  1065. Extrn       strcmp:near
  1066. Public      ssort
  1067.  
  1068. Model Tiny
  1069. P386
  1070. CodeSeg
  1071.  
  1072. ;****************** ssort() -- Sort an array of strings
  1073. ;void ssort(char **ary, int size);
  1074.  
  1075. ary         equ bp+6
  1076. max         equ bp+4
  1077.  
  1078. Proc        ssort
  1079.  
  1080.             push bp                 ;Set up stack frame
  1081.             mov bp,sp
  1082.             pusha                   ;Save all registers
  1083.  
  1084.             mov bx,[ary]            ;Call recursive routine
  1085.             xor cx,cx
  1086.             mov dx,[max]
  1087.             dec dx
  1088.             add dx,dx
  1089.             call p1_qsort
  1090.  
  1091.             popa                    ;Restore registers
  1092.             pop bp                  ;Delete stack frame
  1093.             ret 4                   ;Return
  1094.  
  1095. p1_qsort:   cmp cx,dx               ;One element, return
  1096.             jne $+3
  1097.             ret
  1098.             pusha
  1099.  
  1100.             mov ax,dx               ;Two elements, sort them
  1101.             sub ax,cx
  1102.             cmp ax,2
  1103.             jne p1_cont
  1104.  
  1105.             mov si,cx               ;SI, DI = low, high
  1106.             mov di,dx
  1107.  
  1108.             mov ax,[bx+si]          ;Check them
  1109.             push ax [word bx+di]
  1110.             call strcmp
  1111.             test ax,ax
  1112.             jle p1_done
  1113.  
  1114.             push [word bx+si]       ;Switch them
  1115.             push [word bx+di]
  1116.             pop [word bx+si]
  1117.             pop [word bx+di]
  1118.             jmp p1_done
  1119.  
  1120. p1_cont:    mov si,cx               ;AX = middle element
  1121.             add si,dx
  1122.             shr si,2
  1123.             add si,si
  1124.             mov ax,[bx+si]
  1125.  
  1126.             mov si,cx               ;SI = low, DI = high
  1127.             mov di,dx
  1128.  
  1129. p1_loop:    cmp si,dx               ;While [BX+SI] < AX and
  1130.             jge p1_loop2            ; SI < DX, advance SI
  1131.             push ax ax [word bx+si]
  1132.             call strcmp
  1133.             pop ax
  1134.             jle p1_loop2
  1135.             add si,2
  1136.             jmp p1_loop
  1137.  
  1138. p1_loop2:   cmp di,cx               ;While [BX+DI] > AX and
  1139.             jle p1_cont2            ; DI > CX, advance DI
  1140.             push ax ax [word bx+di]
  1141.             call strcmp
  1142.             pop ax
  1143.             jge p1_cont2
  1144.             sub di,2
  1145.             jmp p1_loop2
  1146.  
  1147. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  1148.             jge p1_rec
  1149.  
  1150.             push [word bx+si]       ;Swap elements
  1151.             push [word bx+di]
  1152.             pop [word bx+si]
  1153.             pop [word bx+di]
  1154.             add si,2                ;Advance SI, DI
  1155.             sub di,2
  1156.  
  1157.             jmp p1_loop             ;Loop back
  1158.  
  1159. p1_rec:     cmp cx,si               ;If first half isn't empty,
  1160.             je p1_skip1             ;recurse to sort it
  1161.             xchg dx,di
  1162.             call p1_qsort
  1163.             xchg dx,di
  1164.  
  1165. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  1166.             je p1_done              ;recurse to sort it
  1167.             xchg cx,si
  1168.             call p1_qsort
  1169.             xchg cx,si
  1170.  
  1171. p1_done:    popa                    ;Restore registers
  1172. p1_ret:     ret                     ;Return
  1173.  
  1174. EndP        ssort
  1175.  
  1176. End
  1177.  
  1178. ~~~C_XSORT
  1179. Ideal
  1180.  
  1181. Public      xsort
  1182.  
  1183. Model Tiny
  1184. P386
  1185. CodeSeg
  1186.  
  1187. ;****************** xsort() -- Sort array, generalized
  1188. ;void xsort(void **ary, int size, void *func);
  1189.  
  1190. ary         equ bp+8
  1191. max         equ bp+6
  1192. func        equ bp+4
  1193.  
  1194. Proc        xsort
  1195.  
  1196.             push bp                 ;Set up stack frame
  1197.             mov bp,sp
  1198.             pusha                   ;Save all registers
  1199.  
  1200.             mov bx,[ary]            ;Call recursive routine
  1201.             xor cx,cx
  1202.             mov dx,[max]
  1203.             dec dx
  1204.             add dx,dx
  1205.             call p1_qsort
  1206.  
  1207.             popa                    ;Restore registers
  1208.             pop bp                  ;Delete stack frame
  1209.             ret 4                   ;Return
  1210.  
  1211. p1_qsort:   cmp cx,dx               ;One element, return
  1212.             jne $+3
  1213.             ret
  1214.             pusha
  1215.  
  1216.             mov ax,dx               ;Two elements, sort them
  1217.             sub ax,cx
  1218.             cmp ax,2
  1219.             jne p1_cont
  1220.  
  1221.             mov si,cx               ;SI, DI = low, high
  1222.             mov di,dx
  1223.  
  1224.             mov ax,[bx+si]          ;Check them
  1225.             push ax [word bx+di]
  1226.             call [word func]
  1227.             test ax,ax
  1228.             jle p1_done
  1229.  
  1230.             push [word bx+si]       ;Switch them
  1231.             push [word bx+di]
  1232.             pop [word bx+si]
  1233.             pop [word bx+di]
  1234.             jmp p1_done
  1235.  
  1236. p1_cont:    mov si,cx               ;AX = middle element
  1237.             add si,dx
  1238.             shr si,2
  1239.             add si,si
  1240.             mov ax,[bx+si]
  1241.  
  1242.             mov si,cx               ;SI = low, DI = high
  1243.             mov di,dx
  1244.  
  1245. p1_loop:    cmp si,dx               ;While [BX+SI] < AX and
  1246.             jge p1_loop2            ; SI < DX, advance SI
  1247.             push ax ax [word bx+si]
  1248.             call [word func]
  1249.             pop ax
  1250.             jle p1_loop2
  1251.             add si,2
  1252.             jmp p1_loop
  1253.  
  1254. p1_loop2:   cmp di,cx               ;While [BX+DI] > AX and
  1255.             jle p1_cont2            ; DI > CX, advance DI
  1256.             push ax ax [word bx+di]
  1257.             call [word func]
  1258.             pop ax
  1259.             jge p1_cont2
  1260.             sub di,2
  1261.             jmp p1_loop2
  1262.  
  1263. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  1264.             jge p1_rec
  1265.  
  1266.             push [word bx+si]       ;Swap elements
  1267.             push [word bx+di]
  1268.             pop [word bx+si]
  1269.             pop [word bx+di]
  1270.             add si,2                ;Advance SI, DI
  1271.             sub di,2
  1272.  
  1273.             jmp p1_loop             ;Loop back
  1274.  
  1275. p1_rec:     cmp cx,si               ;If first half isn't empty,
  1276.             je p1_skip1             ;recurse to sort it
  1277.             xchg dx,di
  1278.             call p1_qsort
  1279.             xchg dx,di
  1280.  
  1281. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  1282.             je p1_done              ;recurse to sort it
  1283.             xchg cx,si
  1284.             call p1_qsort
  1285.             xchg cx,si
  1286.  
  1287. p1_done:    popa                    ;Restore registers
  1288. p1_ret:     ret                     ;Return
  1289.  
  1290. EndP        xsort
  1291.  
  1292. End
  1293.  
  1294. ~~~C_LSHL
  1295. Ideal
  1296.  
  1297. Public      lshl
  1298.  
  1299. Model Tiny
  1300. CodeSeg
  1301. P386
  1302.  
  1303. ;****************** lshl() -- Shift long integer to the left
  1304. ;long lshl(long x, int d);    Included for compatibility.
  1305.  
  1306. x           equ bp+6
  1307. d           equ bp+4
  1308.  
  1309. Proc        lshl
  1310.  
  1311.             push bp                 ;Set up stack frame
  1312.             mov bp,sp
  1313.             push ebx cx             ;Save registers
  1314.  
  1315.             mov ebx,[x]             ;EBX = x
  1316.             mov cl,[d]              ;CL = distance
  1317.             shl ebx,cl              ;Shift left
  1318.             xchg ax,bx              ;DX:AX = result
  1319.             shr ebx,16
  1320.             mov dx,bx
  1321.  
  1322.             pop cx ebx              ;Restore registers
  1323.             pop bp                  ;Delete stack frame
  1324.             ret 6                   ;Return
  1325.  
  1326. EndP        lshl
  1327.  
  1328. End
  1329.  
  1330. ~~~C_LSHR
  1331. Ideal
  1332.  
  1333. Public      lshr
  1334.  
  1335. Model Tiny
  1336. CodeSeg
  1337. P386
  1338.  
  1339. ;****************** lshr() -- Shift long integer to the right
  1340. ;long lshr(long x, int d);    Included for compatibility.
  1341.  
  1342. x           equ bp+6
  1343. d           equ bp+4
  1344.  
  1345. Proc        lshr
  1346.  
  1347.             push bp                 ;Set up stack frame
  1348.             mov bp,sp
  1349.             push ebx cx             ;Save registers
  1350.  
  1351.             mov ebx,[x]             ;EBX = x
  1352.             mov cl,[d]              ;CL = distance
  1353.             shr ebx,cl              ;Shift right
  1354.             xchg ax,bx              ;DX:AX = result
  1355.             shr ebx,16
  1356.             mov dx,bx
  1357.  
  1358.             pop cx ebx              ;Restore registers
  1359.             pop bp                  ;Delete stack frame
  1360.             ret 6                   ;Return
  1361.  
  1362. EndP        lshr
  1363.  
  1364. End
  1365.  
  1366. ~~~C_LSAR
  1367. Ideal
  1368.  
  1369. Public      lsar
  1370.  
  1371. Model Tiny
  1372. CodeSeg
  1373. P386
  1374.  
  1375. ;****************** lsar() -- Shift long integer to the right, signed
  1376. ;long lsar(long x, int d);    Included for compatibility.
  1377.  
  1378. x           equ bp+6
  1379. d           equ bp+4
  1380.  
  1381. Proc        lsar
  1382.  
  1383.             push bp                 ;Set up stack frame
  1384.             mov bp,sp
  1385.             push ebx cx             ;Save registers
  1386.  
  1387.             mov ebx,[x]             ;EBX = x
  1388.             mov cl,[d]              ;CL = distance
  1389.             sar ebx,cl              ;Shift right, signed
  1390.             xchg ax,bx              ;DX:AX = result
  1391.             shr ebx,16
  1392.             mov dx,bx
  1393.  
  1394.             pop cx ebx              ;Restore registers
  1395.             pop bp                  ;Delete stack frame
  1396.             ret 6                   ;Return
  1397.  
  1398. EndP        lsar
  1399.  
  1400. End
  1401.  
  1402. ~~~C_LMUL
  1403. Ideal
  1404.  
  1405. Public      lmul
  1406.  
  1407. Model Tiny
  1408. CodeSeg
  1409. P386
  1410.  
  1411. ;****************** lmul() -- Multiply long integers
  1412. ;long lmul(long x, long y);   Included for compatibility.
  1413.  
  1414. x           equ bp+8
  1415. y           equ bp+4
  1416.  
  1417. Proc        lmul
  1418.  
  1419.             push bp                 ;Set up stack frame
  1420.             mov bp,sp
  1421.             push ebx                ;Save registers
  1422.  
  1423.             mov ebx,[x]             ;EBX = x * y
  1424.             imul ebx,[y]
  1425.             xchg ax,bx              ;DX:AX = result
  1426.             shr ebx,16
  1427.             mov dx,bx
  1428.  
  1429.             pop ebx                 ;Restore registers
  1430.             pop bp                  ;Delete stack frame
  1431.             ret 8                   ;Return
  1432.  
  1433. EndP        lmul
  1434.  
  1435. End
  1436.  
  1437. ~~~C_LIMUL
  1438. Ideal
  1439.  
  1440. Public      limul
  1441.  
  1442. Model Tiny
  1443. CodeSeg
  1444. P386
  1445.  
  1446. ;****************** limul() -- Multiply long integers, signed
  1447. ;long limul(long x, long y);   Included for compatibility
  1448.  
  1449. x           equ bp+8
  1450. y           equ bp+4
  1451.  
  1452. Proc        limul
  1453.  
  1454.             push bp                 ;Set up stack frame
  1455.             mov bp,sp
  1456.             push ebx                ;Save registers
  1457.  
  1458.             mov ebx,[x]             ;EBX = x * y
  1459.             imul ebx,[y]
  1460.             xchg ax,bx              ;DX:AX = result
  1461.             shr ebx,16
  1462.             mov dx,bx
  1463.  
  1464.             pop ebx                 ;Restore registers
  1465.             pop bp                  ;Delete stack frame
  1466.             ret 8                   ;Return
  1467.  
  1468. EndP        limul
  1469.  
  1470. End
  1471.  
  1472. ~~~C_LDIV
  1473. Ideal
  1474.  
  1475. Public      ldiv
  1476.  
  1477. Model Tiny
  1478. CodeSeg
  1479. P386
  1480.  
  1481. ;****************** ldiv() -- Divide long integers
  1482. ;long ldiv(long x, long y);   Included for compatibility.
  1483.  
  1484. x           equ bp+8
  1485. y           equ bp+4
  1486.  
  1487. Proc        ldiv
  1488.  
  1489.             push bp                 ;Set up stack frame
  1490.             mov bp,sp
  1491.             push ebx ecx esi        ;Save registers
  1492.  
  1493.             mov ecx,edx             ;Save EDX:EAX
  1494.             xchg ebx,eax
  1495.             mov eax,[x]             ;EAX = x / y
  1496.             mov esi,[y]
  1497.             xor edx,edx
  1498.             div esi
  1499.             mov edx,ecx             ;Restore EDX:EAX
  1500.             xchg ebx,eax
  1501.             xchg ax,bx              ;DX:AX = result
  1502.             shr ebx,16
  1503.             mov dx,bx
  1504.  
  1505.             pop esi ecx ebx         ;Restore registers
  1506.             pop bp                  ;Delete stack frame
  1507.             ret 8                   ;Return
  1508.  
  1509. EndP        ldiv
  1510.  
  1511. End
  1512.  
  1513. ~~~C_LIDIV
  1514. Ideal
  1515.  
  1516. Public      lidiv
  1517.  
  1518. Model Tiny
  1519. CodeSeg
  1520. P386
  1521.  
  1522. ;****************** lidiv() -- Divide long integers, signed
  1523. ;long lidiv(long x, long y);   Included for compatibility.
  1524.  
  1525. x           equ bp+8
  1526. y           equ bp+4
  1527.  
  1528. Proc        lidiv
  1529.  
  1530.             push bp                 ;Set up stack frame
  1531.             mov bp,sp
  1532.             push ebx ecx esi        ;Save registers
  1533.  
  1534.             mov ecx,edx             ;Save EDX:EAX
  1535.             xchg ebx,eax
  1536.             mov eax,[x]             ;EAX = x / y
  1537.             mov esi,[y]
  1538.             cdq
  1539.             idiv esi
  1540.             mov edx,ecx             ;Restore EDX:EAX
  1541.             xchg ebx,eax
  1542.             xchg ax,bx              ;DX:AX = result
  1543.             shr ebx,16
  1544.             mov dx,bx
  1545.  
  1546.             pop esi ecx ebx         ;Restore registers
  1547.             pop bp                  ;Delete stack frame
  1548.             ret 8                   ;Return
  1549.  
  1550. EndP        lidiv
  1551.  
  1552. End
  1553.  
  1554. ~~~C_LMOD
  1555. Ideal
  1556.  
  1557. Public      lmod
  1558.  
  1559. Model Tiny
  1560. CodeSeg
  1561. P386
  1562.  
  1563. ;****************** lmod() -- Modulo on long integers
  1564. ;long lmod(long x, long y);   Included for compatibility.
  1565.  
  1566. x           equ bp+8
  1567. y           equ bp+4
  1568.  
  1569. Proc        lmod
  1570.  
  1571.             push bp                 ;Set up stack frame
  1572.             mov bp,sp
  1573.             push ebx ecx esi        ;Save registers
  1574.  
  1575.             mov ecx,edx             ;Save EDX:EAX
  1576.             xchg ebx,eax
  1577.             mov eax,[x]             ;EAX = x / y
  1578.             mov esi,[y]
  1579.             xor edx,edx
  1580.             div esi
  1581.             xchg edx,ecx            ;Restore EDX:EAX
  1582.             xchg ebx,eax
  1583.             xchg ax,cx              ;DX:AX = result
  1584.             shr ecx,16
  1585.             mov dx,cx
  1586.  
  1587.             pop esi ecx ebx         ;Restore registers
  1588.             pop bp                  ;Delete stack frame
  1589.             ret 8                   ;Return
  1590.  
  1591. EndP        lmod
  1592.  
  1593. End
  1594.  
  1595. ~~~C_LIMOD
  1596. Ideal
  1597.  
  1598. Public      limod
  1599.  
  1600. Model Tiny
  1601. CodeSeg
  1602. P386
  1603.  
  1604. ;****************** limod() -- Modulo on long integers, signed
  1605. ;long limod(long x, long y);   Included for compatibility.
  1606.  
  1607. x           equ bp+8
  1608. y           equ bp+4
  1609.  
  1610. Proc        limod
  1611.  
  1612.             push bp                 ;Set up stack frame
  1613.             mov bp,sp
  1614.             push ebx ecx esi        ;Save registers
  1615.  
  1616.             mov ecx,edx             ;Save EDX:EAX
  1617.             xchg ebx,eax
  1618.             mov eax,[x]             ;EAX = x / y
  1619.             mov esi,[y]
  1620.             cdq
  1621.             idiv esi
  1622.             xchg edx,ecx            ;Restore EDX:EAX
  1623.             xchg ebx,eax
  1624.             xchg ax,cx              ;DX:AX = result
  1625.             shr ecx,16
  1626.             mov dx,cx
  1627.  
  1628.             pop esi ecx ebx         ;Restore registers
  1629.             pop bp                  ;Delete stack frame
  1630.             ret 8                   ;Return
  1631.  
  1632. EndP        limod
  1633.  
  1634. End
  1635.  
  1636. ~~~C_FIXMUL
  1637. Ideal
  1638.  
  1639. Public      fixmul
  1640.  
  1641. Model Tiny
  1642. CodeSeg
  1643. P386
  1644.  
  1645. ;****************** fixmul() -- Multiply fixed point numbers
  1646. ;long fixmul(long x, long y);   48 clocks (486)
  1647.  
  1648. x           equ bp+8
  1649. y           equ bp+4
  1650.  
  1651. Proc        fixmul
  1652.  
  1653.             push bp                 ;Set up stack frame
  1654.             mov bp,sp
  1655.             push ebx ecx            ;Save registers
  1656.  
  1657.             mov ecx,edx             ;Save EDX:EAX
  1658.             xchg ebx,eax
  1659.             mov eax,[x]             ;EAX = x / y (fixed point)
  1660.             mov edx,[y]
  1661.             imul edx
  1662.             shrd eax,edx,16
  1663.             mov edx,ecx             ;Restore EDX:EAX
  1664.             xchg ebx,eax
  1665.             xchg ax,bx              ;DX:AX = result
  1666.             shr ebx,16
  1667.             mov dx,bx
  1668.  
  1669.             pop ecx ebx             ;Restore registers
  1670.             pop bp                  ;Delete stack frame
  1671.             ret 8                   ;Return
  1672.  
  1673. EndP        fixmul
  1674.  
  1675. End
  1676.  
  1677. ~~~C_FIXDIV
  1678. Ideal
  1679.  
  1680. Public      fixdiv
  1681.  
  1682. Model Tiny
  1683. CodeSeg
  1684. P386
  1685.  
  1686. ;****************** fixdiv() -- Divide fixed point numbers
  1687. ;long fixdiv(long x, long y);   57-86 clocks (486)
  1688.  
  1689. x           equ bp+8
  1690. y           equ bp+4
  1691.  
  1692. Proc        fixdiv
  1693.  
  1694.             push bp                 ;Set up stack frame
  1695.             mov bp,sp
  1696.             push ebx ecx esi        ;Save registers
  1697.  
  1698.             mov ecx,edx             ;Save EDX:EAX
  1699.             xchg ebx,eax
  1700.             mov eax,[x]             ;EAX = x / y (fixed point)
  1701.             mov esi,[y]
  1702.             cdq
  1703.             shld edx,eax,16
  1704.             shl eax,16
  1705.             idiv esi
  1706.             mov edx,ecx             ;Restore EDX:EAX
  1707.             xchg ebx,eax
  1708.             xchg ax,bx              ;DX:AX = result
  1709.             shr ebx,16
  1710.             mov dx,bx
  1711.  
  1712.             pop esi ecx ebx         ;Restore registers
  1713.             pop bp                  ;Delete stack frame
  1714.             ret 8                   ;Return
  1715.  
  1716. EndP        fixdiv
  1717.  
  1718. End
  1719.  
  1720. ~~~C_TRIG
  1721. Ideal
  1722.  
  1723. Extrn       fixdiv:near
  1724. Public      sine, cosine, tangent, cotangent
  1725. Public      secant, cosecant
  1726.  
  1727. Model Tiny
  1728. CodeSeg
  1729. P386
  1730.  
  1731. ;****************** TaylorSine() -- Calculate sine by Taylor series
  1732. ;long TaylorSine(long x);           Returns value in EBX
  1733.  
  1734. ; *──────────────────────────────────────────────────*
  1735. ; │               x^3     x^5     x^7     x^9        │
  1736. ; │ sin(x) = x - ───── + ───── - ───── + ───── - ... │
  1737. ; │               3 !     5 !     7 !     9 !        │
  1738. ; *──────────────────────────────────────────────────*
  1739.  
  1740. x           equ bp+4
  1741.  
  1742. Proc        TaylorSine
  1743.  
  1744.             push bp                 ;Set up stack frame
  1745.             mov bp,sp
  1746.             push eax ecx edx esi    ;Save registers
  1747.  
  1748.             mov eax,[x]             ;First term = x
  1749.             xor ebx,ebx             ;Result = 0
  1750.             mov esi,1               ;Count = 1
  1751.  
  1752. TS_loop:    add ebx,eax             ;Add in term
  1753.  
  1754.             imul [dword x]          ;term = last-term * x^2
  1755.             shrd eax,edx,16
  1756.             imul [dword x]
  1757.             shrd eax,edx,16
  1758.             add esi,2               ;n = n + 2
  1759.             mov ecx,esi             ;ECX = n * (n - 1)
  1760.             dec ecx
  1761.             imul ecx,esi
  1762.             cdq                     ;term = last-term * x^2 / n(n-1)
  1763.             idiv ecx
  1764.             neg eax                 ;Invert sign
  1765.  
  1766.             test eax,eax            ;Loop while not zero
  1767.             jnz TS_loop
  1768.  
  1769.             pop esi edx ecx eax     ;Restore registers
  1770.             pop bp                  ;Delete stack frame
  1771.             ret 4                   ;Return
  1772.  
  1773. EndP        TaylorSine
  1774.  
  1775. Pi          dd 0003243Fh            ;Pi   (3.243F6A88... hex)
  1776. TwoPi       dd 0006487Fh            ;Pi*2 (6.487ED511... hex)
  1777. HalfPi      dd 00019220h            ;Pi/2 (1.921FB544... hex)
  1778.  
  1779. ;****************** sine() -- Trigonometric sine function
  1780. ;long sine(long x);
  1781.  
  1782. x           equ bp+4
  1783.  
  1784. Proc        sine
  1785.  
  1786.             push bp                 ;Set up stack frame
  1787.             mov bp,sp
  1788.             push ebx                ;Save EBX
  1789.  
  1790.             mov ebx,[x]             ;EBX = x + Pi
  1791.             add ebx,[Pi]
  1792.             push ebx [TwoPi]        ;Divide by 2*Pi
  1793.             call fixdiv
  1794.             movsx ebx,dx            ;EBX = integer part
  1795.             imul ebx,[TwoPi]        ;Multiply by 2*Pi
  1796.  
  1797.             neg ebx                 ;EBX = x - EBX
  1798.             add ebx,[x]
  1799.  
  1800.             push ebx                ;Calculate sine
  1801.             call TaylorSine
  1802.             xchg ax,bx              ;Result in DX:AX
  1803.             shr ebx,16
  1804.             mov dx,bx
  1805.  
  1806.             pop ebx                 ;Restore EBX
  1807.             pop bp                  ;Delete stack frame
  1808.             ret 4                   ;Return
  1809.  
  1810. EndP        sine
  1811.  
  1812. ;****************** cosine() -- Trigonometric cosine function
  1813. ;long cosine(long x);
  1814.  
  1815. x           equ bp+4
  1816.  
  1817. Proc        cosine
  1818.  
  1819.             push bp                 ;Set up stack frame
  1820.             mov bp,sp
  1821.  
  1822.             mov dx,[x+2]            ;DX:AX = x
  1823.             mov ax,[x]
  1824.             add ax,[word HalfPi]    ; x + Pi+2
  1825.             adc dx,[word HalfPi+2]
  1826.             push dx ax              ;cos(x) = sin(x + Pi/4)
  1827.             call sine
  1828.  
  1829.             pop bp                  ;Delete stack frame
  1830.             ret 4                   ;Return
  1831.  
  1832. EndP        cosine
  1833.  
  1834. ;****************** tangent() -- Trigonometric tangent function
  1835. ;long tangent(long x);
  1836.  
  1837. x           equ bp+4
  1838.  
  1839. Proc        tangent
  1840.  
  1841.             push bp                 ;Set up stack frame
  1842.             mov bp,sp
  1843.             push bx cx              ;Save registers
  1844.  
  1845.             push [dword x]          ;CX:BX = sin(x)
  1846.             call sine
  1847.             mov cx,dx
  1848.             xchg bx,ax
  1849.             push [dword x]          ;DX:AX = cos(x)
  1850.             call cosine
  1851.             push cx bx dx ax        ;tan(x) = sin(x) / cos(x)
  1852.             call fixdiv
  1853.  
  1854.             pop cx bx               ;Restore registers
  1855.             pop bp                  ;Delete stack frame
  1856.             ret 4                   ;Return
  1857.  
  1858. EndP        tangent
  1859.  
  1860. ;****************** cotangent() -- Trigonometric cotangent function
  1861. ;long cotangent(long x);
  1862.  
  1863. x           equ bp+4
  1864.  
  1865. Proc        cotangent
  1866.  
  1867.             push bp                 ;Set up stack frame
  1868.             mov bp,sp
  1869.             push bx cx              ;Save registers
  1870.  
  1871.             push [dword x]          ;CX:BX = sin(x)
  1872.             call sine
  1873.             mov cx,dx
  1874.             xchg bx,ax
  1875.             push [dword x]          ;DX:AX = cos(x)
  1876.             call cosine
  1877.             push dx ax cx bx        ;cot(x) = cos(x) / sin(x)
  1878.             call fixdiv
  1879.  
  1880.             pop cx bx               ;Restore registers
  1881.             pop bp                  ;Delete stack frame
  1882.             ret 4                   ;Return
  1883.  
  1884. EndP        cotangent
  1885.  
  1886. ;****************** secant() -- Trigonometric secant function
  1887. ;long secant(long x);
  1888.  
  1889. x           equ bp+4
  1890.  
  1891. Proc        secant
  1892.  
  1893.             push bp                 ;Set up stack frame
  1894.             mov bp,sp
  1895.  
  1896.             push [dword x]          ;DX:AX = cos(x)
  1897.             call cosine
  1898.             push 1 0 dx ax          ;sec(x) = 1 / cos(x)
  1899.             call fixdiv
  1900.  
  1901.             pop bp                  ;Delete stack frame
  1902.             ret 4                   ;Return
  1903.  
  1904. EndP        secant
  1905.  
  1906. ;****************** cosecant() -- Trigonometric cosecant function
  1907. ;long cosecant(long x);
  1908.  
  1909. x           equ bp+4
  1910.  
  1911. Proc        cosecant
  1912.  
  1913.             push bp                 ;Set up stack frame
  1914.             mov bp,sp
  1915.  
  1916.             push [dword x]          ;DX:AX = cos(x)
  1917.             call sine
  1918.             push 1 0 dx ax          ;csc(x) = 1 / sin(x)
  1919.             call fixdiv
  1920.  
  1921.             pop bp                  ;Delete stack frame
  1922.             ret 4                   ;Return
  1923.  
  1924. EndP        cosecant
  1925.  
  1926. End
  1927.  
  1928. ~~~C_FIXTOA
  1929. Ideal
  1930.  
  1931. Public      fixtoa
  1932.  
  1933. Model Tiny
  1934. CodeSeg
  1935. P386
  1936.  
  1937. ;****************** fixtoa() -- Convert fixed point number to string
  1938. ;void fixtoa(int n, char *strp);
  1939.  
  1940. n           equ bp+6
  1941. strp        equ bp+4
  1942.  
  1943. Proc        fixtoa
  1944.  
  1945.             push bp                 ;Set up stack frame
  1946.             mov bp,sp
  1947.             pusha                   ;Save all registers
  1948.  
  1949.             mov di,[strp]           ;DI = string pointer
  1950.             mov dx,[n+2]            ;DX:AX = n
  1951.             mov ax,[n]
  1952.  
  1953.             test dx,dx              ;Negative?
  1954.             jge p1_noneg
  1955.             mov [byte di],'-'       ;Store minus sign
  1956.             inc di
  1957.             neg dx                  ;Make it positive
  1958.             neg ax
  1959.             sbb dx,0
  1960.  
  1961. p1_noneg:   push dx                 ;Save DX
  1962.             xor bx,bx               ;Zero rem flag
  1963.             add ax,ax               ;Shift out high bit
  1964.             adc bx,0                ;BX = rem flag
  1965.             shr ax,1                ;Restore AX
  1966.  
  1967.             mov cx,50000            ;AX = AX * 50000
  1968.             mul cx
  1969.             shr ax,15               ;AX = AX / 32768
  1970.             shl dx,1
  1971.             or ax,dx
  1972.             pop dx                  ;Restore DX
  1973.             push bx ax              ;Save BX, AX
  1974.  
  1975.             xchg dx,ax              ;Integer part in AX
  1976.  
  1977.             xor cx,cx               ;Zero CX
  1978.             mov si,10               ;SI = 10
  1979.  
  1980. p1_dloop:   xor dx,dx               ;Divide by 10
  1981.             div si
  1982.             mov bl,dl               ;Remainder in BL
  1983.             add bl,30h              ;Convert to digit
  1984.             push bx                 ;Push digit
  1985.             inc cx
  1986.             test ax,ax              ;Loop back
  1987.             jnz p1_dloop
  1988.  
  1989. p1_ploop:   pop ax                  ;Pop digit
  1990.             mov [di],al             ;Store digit
  1991.             inc di
  1992.             loop p1_ploop           ;Loop back
  1993.  
  1994.             mov [byte di],'.'       ;Store decimal point
  1995.             inc di
  1996.             pop ax bx               ;Restore low data
  1997.             xor dx,dx               ;Zero DX
  1998.             test bx,bx              ;Check for high part
  1999.             jz p1_nohigh
  2000.  
  2001.             add ax,50000            ;Add in 50000
  2002.             adc dx,0
  2003.  
  2004. p1_nohigh:  mov si,10               ;SI = 10
  2005.             mov cx,5                ;5 digits
  2006.             jmp p1_skip1
  2007.  
  2008. p1_dloopb:  xor dx,dx               ;Zero DX
  2009. p1_skip1:   div si                  ;Divide by 10
  2010.             mov bl,dl               ;Remainder in BL
  2011.             add bl,30h              ;Convert to digit
  2012.             push bx                 ;Push digit
  2013.             loop p1_dloopb          ;Loop back
  2014.  
  2015.             mov cx,5                ;5 digits
  2016.  
  2017. p1_ploopb:  pop ax                  ;Pop digit
  2018.             mov [di],al             ;Store digit
  2019.             inc di
  2020.             loop p1_ploopb          ;Loop back
  2021.  
  2022.             mov [byte di],0         ;Add the null byte
  2023.  
  2024. p1_done:    popa                    ;Restore registers
  2025.             pop bp                  ;Delete stack frame
  2026.             ret 6                   ;Return
  2027.  
  2028. EndP        fixtoa
  2029.  
  2030. End
  2031.  
  2032. ~~~C_ATOFIX
  2033. Ideal
  2034.  
  2035. Public      atofix
  2036.  
  2037. Model Tiny
  2038. CodeSeg
  2039. P386
  2040.  
  2041. ;****************** atofix() -- Convert string to fixed point number
  2042. ;long atofix(char *strp);
  2043.  
  2044. strp        equ bp+4
  2045.  
  2046. Proc        atofix
  2047.  
  2048.             push bp                 ;Set up stack frame
  2049.             mov bp,sp
  2050.             push bx cx si di bp     ;Save registers
  2051.  
  2052.             mov si,[strp]           ;SI = string
  2053.  
  2054.             xor ax,ax               ;AX = 0
  2055.             xor bh,bh               ;BH = 0
  2056.             mov cx,10               ;CX = 10
  2057.  
  2058. p1_ploop:   mov bl,[si]             ;Load char
  2059.             inc si
  2060.             cmp bl,' '              ;Loop while char is space
  2061.             je p1_ploop             ;(20h, or 09h thru 0Dh)
  2062.             cmp bl,9
  2063.             jna p1_go
  2064.             cmp bl,13
  2065.             jbe p1_ploop
  2066.  
  2067. p1_go:      xor bp,bp               ;BP = 0
  2068.             cmp bl,'+'              ;If char = '+', ignore
  2069.             je p1_loop
  2070.             cmp bl,'-'              ;If char <> '-', keep it
  2071.             jne p1_skip
  2072.             inc bp                  ;Set negative flag
  2073.  
  2074. p1_loop:    mov bl,[si]             ;Load char
  2075.             inc si
  2076.  
  2077. p1_skip:    xor dx,dx               ;Clear DX
  2078.             cmp bl,'.'              ;Decimal point, continue
  2079.             je p1_cont
  2080.             cmp bl,'9'              ;Not a digit, finish
  2081.             ja p1_finish
  2082.             sub bl,'0'
  2083.             jc p1_finish
  2084.  
  2085.             mul cx                  ;Multiply by 10
  2086.             add ax,bx               ;Add in digit...
  2087.             jmp p1_loop             ;Loop back
  2088.  
  2089. p1_cont:    push ax                 ;Save integer part
  2090.             xor ax,ax               ;Zero AX
  2091.             mov di,1                ;DI = 1
  2092.  
  2093. p1_floop:   mov bl,[si]             ;Load char
  2094.             inc si
  2095.  
  2096.             cmp bl,'9'              ;Not a digit, finish
  2097.             ja p1_ffinish
  2098.             sub bl,'0'
  2099.             jc p1_ffinish
  2100.  
  2101.             mul cx                  ;Multiply by 10
  2102.             add ax,bx               ;Add in digit...
  2103.             adc dx,0
  2104.             imul di,10              ;Multiply divisor by 10
  2105.             jnc p1_floop            ;Loop while < 5 digits
  2106.  
  2107.             shr dx,1                ;5 digits, divide by 2
  2108.             rcr ax,1                ;and set DI to 50000
  2109.             mov di,50000            ;instead of 100000
  2110.  
  2111. p1_ffinish: xchg dx,ax              ;Multiply by 65536
  2112.             xor ax,ax
  2113.             div di                  ;Divide by 10^digits
  2114.             xchg dx,ax              ;Fractional part in DX
  2115.             pop ax                  ;Restore integer part
  2116.  
  2117. p1_finish:  xchg dx,ax              ;DX:AX = number
  2118.  
  2119.             dec bp                  ;Positive, don't negate
  2120.             jl p1_done
  2121.  
  2122.             neg dx                  ;Negate the result
  2123.             neg ax
  2124.             sbb dx,0
  2125.  
  2126. p1_done:    pop bp di si cx bx      ;Restore registers
  2127.             pop bp                  ;Delete stack frame
  2128.             ret 2                   ;Return
  2129.  
  2130. EndP        atofix
  2131.  
  2132. End
  2133.  
  2134. ~~~C_BITS
  2135. Ideal
  2136.  
  2137. Public      bitcnt,highbit
  2138.  
  2139. Model Tiny
  2140. P386
  2141. CodeSeg
  2142.  
  2143. ;****************** bitcnt() -- Count set bits in integer
  2144. ;int bitcnt(int x);
  2145.  
  2146. x           equ bp+4
  2147.  
  2148. Proc        bitcnt
  2149.  
  2150.             push bp                 ;Set up stack frame
  2151.             mov bp,sp
  2152.             push bx cx              ;Save registers
  2153.  
  2154.             xor cx,cx               ;CX = 0
  2155.             mov ax,[x]              ;AX = number
  2156.             test ax,ax              ;Zero?
  2157.             jz p1_done
  2158.  
  2159. p1_loop:    mov bx,ax               ;Kill last bit
  2160.             dec bx
  2161.             and ax,bx
  2162.             loopnz p1_loop          ;Loop while not zero
  2163.  
  2164. p1_done:    sub ax,cx               ;Negative of CX
  2165.  
  2166.             pop cx bx               ;Restore registers
  2167.             pop bp                  ;Delete stack frame
  2168.             ret 2                   ;Return
  2169.  
  2170. EndP        bitcnt
  2171.  
  2172. ;****************** highbit() -- Find high bit in integer
  2173. ;int highbit(int x);             returns -1 if it was zero
  2174.  
  2175. x           equ bp+4
  2176.  
  2177. Proc        highbit
  2178.  
  2179.             push bp                 ;Set up stack frame
  2180.             mov bp,sp
  2181.  
  2182.             bsr ax,[x]              ;Scan for bit
  2183.             jnz $+5                 ;No bit set?
  2184.             mov ax,-1               ;Return -1
  2185.  
  2186.             pop bp                  ;Delete stack frame
  2187.             ret 2                   ;Return
  2188.  
  2189. EndP        highbit
  2190.  
  2191. End
  2192.  
  2193. ~~~C_SQRT
  2194. Ideal
  2195.  
  2196. Public      sqrt
  2197.  
  2198. Model Tiny
  2199. P386
  2200. CodeSeg
  2201.  
  2202. ;****************** sqrt() -- Returns the square root of a
  2203. ;                             long.  Result is an integer.
  2204. ;int sqrt(long num);          60-350 clocks (486)
  2205.  
  2206.  
  2207. num         equ bp+4
  2208.  
  2209. Proc        sqrt
  2210.  
  2211.             push bp                 ;Set up stack frame
  2212.             mov bp,sp
  2213.             push cx dx              ;Save registers
  2214.  
  2215.             mov ax,[num]            ;DX:AX = num
  2216.             mov dx,[num+2]
  2217.  
  2218.             mov cx,32               ;32 bits
  2219.  
  2220. p1_bloop:   add ax,ax               ;Find the highest set bit
  2221.             adc dx,dx
  2222.             jc p1_gotbit
  2223.             loop p1_bloop
  2224.  
  2225. p1_gotbit:  mov ax,1                ;CX = first guess 2^(log2(n)/2)
  2226.             shr cx,1
  2227.             shl ax,cl
  2228.             xchg cx,ax
  2229.  
  2230. p1_loop:    mov ax,[num]            ;DX:AX = num
  2231.             mov dx,[num+2]
  2232.             div cx                  ;AX = num/guess
  2233.             add cx,ax               ;CX = (guess+(num/guess))/2
  2234.             shr cx,1
  2235.             sub ax,cx               ;If the difference is 1
  2236.             cmp ax,1                ;or less, then done
  2237.             ja p1_loop              ;Loop back
  2238.  
  2239.             xchg ax,cx              ;AX = result
  2240.             pop dx cx               ;Restore registers
  2241.             pop bp                  ;Delete stack frame
  2242.             ret 4                   ;Return
  2243.  
  2244. EndP        sqrt
  2245.  
  2246. End
  2247.  
  2248. ~~~C_ROMAN
  2249. Ideal
  2250.  
  2251. Public      roman
  2252.  
  2253. Model Tiny
  2254. CodeSeg
  2255. P386
  2256.  
  2257. ;****************** roman() -- Convert integer to Roman Numerals
  2258.  
  2259. num         equ bp+6
  2260. buf         equ bp+4
  2261.  
  2262. Proc        roman
  2263.  
  2264.             push bp                 ;Set up stack frame
  2265.             mov bp,sp
  2266.             pusha                   ;Save all registers
  2267.  
  2268.             mov di,[buf]            ;DI = buffer
  2269.             mov dx,[num]            ;DX = number
  2270.             mov si,offset RNTbl_1   ;SI, BX = tables
  2271.             mov bx,offset RNTbl_2
  2272.  
  2273. p1_loop:    lodsw                   ;Load size
  2274.             test ax,ax              ;Done?
  2275.             jz p1_done
  2276.  
  2277. p1_iloop:   cmp dx,ax
  2278.             jl p1_lb
  2279.             mov cx,[bx]             ;AX = code
  2280.             mov [di],cl             ;Store first char
  2281.             inc di
  2282.  
  2283.             cmp ch,'.'              ;If second char, then
  2284.             je p1_ilb               ; store second char
  2285.             mov [di],ch
  2286.             inc di
  2287.  
  2288. p1_ilb:     sub dx,ax               ;Reduce number
  2289.             jmp p1_iloop            ;Loop back
  2290.  
  2291. p1_lb:      add bx,2                ;Advance pointer
  2292.             jmp p1_loop             ;Loop back
  2293.  
  2294. p1_done:    mov [di],al             ;Terminate string
  2295.  
  2296.             popa                    ;Restore registers
  2297.             pop bp                  ;Delete stack frame
  2298.             ret 4                   ;Return
  2299.  
  2300. EndP        roman
  2301.  
  2302. RNTbl_1     dw 1000,900,500,400,100
  2303.             dw 90,50,40,10,9,5,4,1,0
  2304.  
  2305. RNTbl_2     db 'M.CMD.CDC.XCL.XLX.IXV.IVI.'
  2306.  
  2307. End
  2308.  
  2309. ~~~C_CRC16
  2310. Ideal
  2311.  
  2312. Public      crc16
  2313.  
  2314. Model Tiny
  2315. CodeSeg
  2316. P386
  2317.  
  2318. ;****************** crc16() -- Calculate 16-bit CRC
  2319. ;int crc16(void *ptr, int cnt)
  2320.  
  2321. ptr         equ bp+6
  2322. cnt         equ bp+4
  2323.  
  2324. Proc        crc16
  2325.  
  2326.             push bp                 ;Set up stack frame
  2327.             mov bp,sp
  2328.             push bx cx dx si        ;Save registers
  2329.  
  2330.             mov si,[ptr]            ;SI = pointer
  2331.             mov bx,[cnt]            ;BX = count
  2332.  
  2333.             xor dx,dx               ;Start with 0
  2334.  
  2335. p1_loop:    lodsb                   ;Load byte
  2336.             xor dh,al               ;XOR into result
  2337.             mov cx,8                ;8 bits
  2338.  
  2339. p1_iloop:   add dx,dx               ;Shift left
  2340.             jnc $+5                 ;If bit = 1, then
  2341.             xor dx,1021h            ;XOR in CRC value
  2342.             loop p1_iloop           ;Loop back
  2343.  
  2344.             dec bx                  ;Byte loop
  2345.             jnz p1_loop
  2346.  
  2347.             xchg dx,ax              ;Result in AX
  2348.  
  2349. p1_done:    pop si dx cx bx         ;Restore registers
  2350.             pop bp                  ;Delete stack frame
  2351.             ret 4                   ;Return
  2352.  
  2353. EndP        crc16
  2354.  
  2355. End
  2356.  
  2357. ~~~C_CRC32
  2358. Ideal
  2359.  
  2360. Public      crc32
  2361.  
  2362. Model Tiny
  2363. CodeSeg
  2364. P386
  2365.  
  2366. ;****************** crc32() -- Calculate 32-bit CRC
  2367. ;long crc32(void *ptr, int cnt)
  2368.  
  2369. ptr         equ bp+6
  2370. cnt         equ bp+4
  2371.  
  2372. Proc        crc32
  2373.  
  2374.             push bp                 ;Set up stack frame
  2375.             mov bp,sp
  2376.             push bx cx si di        ;Save registers
  2377.  
  2378.             mov si,[ptr]            ;SI = pointer
  2379.             mov bx,[cnt]            ;BX = count
  2380.  
  2381.             xor dx,dx               ;Start with 0
  2382.             xor di,di
  2383.  
  2384. p1_loop:    lodsb                   ;Load byte
  2385.             xor dh,al               ;XOR into result
  2386.             mov cx,8                ;8 bits
  2387.  
  2388. p1_iloop:   add di,di               ;Shift left
  2389.             adc dx,dx
  2390.             jnc $+8                 ;If bit = 1, then
  2391.             xor dx,04C1h            ;XOR in CRC value
  2392.             xor di,1DB7h
  2393.             loop p1_iloop           ;Loop back
  2394.  
  2395.             dec bx                  ;Byte loop
  2396.             jnz p1_loop
  2397.  
  2398.             xchg di,ax              ;Result in DX:AX
  2399.  
  2400. p1_done:    pop di si cx bx         ;Restore registers
  2401.             pop bp                  ;Delete stack frame
  2402.             ret 4                   ;Return
  2403.  
  2404. EndP        crc32
  2405.  
  2406. End
  2407.  
  2408. ; Virtual memory system by Tylisha C. Andersen.
  2409. ; Support routines added by Tenie Remmel.
  2410.  
  2411. ~~~C_VMEM
  2412. Ideal
  2413.  
  2414. Public      vminit,vmclose,vmread,vmwrite
  2415.  
  2416. Model Tiny
  2417. P386
  2418. CodeSeg
  2419.  
  2420. ;****************** vminit() -- Init virtual memory system
  2421. ;int vminit(void);
  2422.  
  2423. Proc        vminit
  2424.  
  2425.             push bp                 ;Set up stack frame
  2426.             mov bp,sp
  2427.  
  2428.             mov ah,0                ;Init VM system
  2429.             call VMproc
  2430.  
  2431.             sbb ax,ax               ;AX = 1 if ok, 0 if not
  2432.             inc ax
  2433.  
  2434.             pop bp                  ;Delete stack frame
  2435.             ret                     ;Return
  2436.  
  2437. EndP        vminit
  2438.  
  2439. ;****************** vmclose() -- Close virtual memory system
  2440. ;int vmclose(void);
  2441.  
  2442. Proc        vmclose
  2443.  
  2444.             push bp                 ;Set up stack frame
  2445.             mov bp,sp
  2446.             push ax                 ;Save AX
  2447.  
  2448.             mov ah,1                ;Close VM system
  2449.             call VMproc
  2450.  
  2451.             pop ax                  ;Restore AX
  2452.             pop bp                  ;Delete stack frame
  2453.             ret                     ;Return
  2454.  
  2455. EndP        vmclose
  2456.  
  2457. ;****************** vmread() -- Read block of virtual memory
  2458. ;int vmread(void *buf, long offs, int len);
  2459.  
  2460. buf         equ bp+10
  2461. offs        equ bp+6
  2462. len         equ bp+4
  2463.  
  2464. Proc        vmread
  2465.  
  2466.             push bp                 ;Set up stack frame
  2467.             mov bp,sp
  2468.             push ebx cx dx          ;Save registers
  2469.  
  2470.             mov ah,2                ;Read VM memory
  2471.             mov dx,[buf]
  2472.             mov ebx,[offs]
  2473.             mov cx,[len]
  2474.             call VMproc
  2475.  
  2476.             sbb ax,ax               ;AX = 1 if ok, 0 if not
  2477.             inc ax
  2478.  
  2479.             pop dx cx ebx           ;Restore registers
  2480.             pop bp                  ;Delete stack frame
  2481.             ret                     ;Return
  2482.  
  2483. EndP        vmread
  2484.  
  2485. ;****************** vmwrite() -- Write block of virtual memory
  2486. ;int vmwrite(void *buf, long offs, int len);
  2487.  
  2488. buf         equ bp+10
  2489. offs        equ bp+6
  2490. len         equ bp+4
  2491.  
  2492. Proc        vmwrite
  2493.  
  2494.             push bp                 ;Set up stack frame
  2495.             mov bp,sp
  2496.             push ebx cx dx          ;Save registers
  2497.  
  2498.             mov ah,3                ;Write VM memory
  2499.             mov dx,[buf]
  2500.             mov ebx,[offs]
  2501.             mov cx,[len]
  2502.             call VMproc
  2503.  
  2504.             sbb ax,ax               ;AX = 1 if ok, 0 if not
  2505.             inc ax
  2506.  
  2507.             pop dx cx ebx           ;Restore registers
  2508.             pop bp                  ;Delete stack frame
  2509.             ret                     ;Return
  2510.  
  2511. EndP        vmwrite
  2512.  
  2513. ;---------------------------- Internal data section
  2514.                               
  2515. xmshandle   dw    0                 ; xms handle        -6
  2516. xmssize     dd    0                 ; xms length        -4
  2517. xmscall     dd    0                 ; xms call point    +0
  2518.  
  2519. fhandle     dw    0                 ; file handle       +4
  2520. fname       db    'C:\$VM$.TMP',0   ; file name         +6
  2521.  
  2522. ;---------------------------- VMproc:  VM call point
  2523. ;                             ------------------------
  2524. ;                             -- ah = 0:  init
  2525. ;                             -- ah = 1:  close
  2526. ;                             -- ah = 2:  read
  2527. ;                                   ds:dx = buffer
  2528. ;                                   ebx = offset in VM
  2529. ;                                   cx = length
  2530. ;                             -- ah = 3:  write
  2531. ;                                   ds:dx = buffer
  2532. ;                                   ebx = offset in VM
  2533. ;                                   cx = length
  2534. ;                             ------------------------
  2535. ;                             Returns cf = error flag
  2536. ;                             ------------------------
  2537. ;                             Offsets and lengths for
  2538. ;                             read/write must be even.
  2539.  
  2540. Proc        VMproc
  2541.  
  2542.             pushad                  ; save all registers
  2543.             push  ds es             ; load frame pointer
  2544.             mov   di, offset xmscall
  2545.  
  2546.             test  ah, ah            ; service 0, init?
  2547.             jne   vmm_cont
  2548.  
  2549.             cmp   [word cs:di+4], 0 ; already initialized?
  2550.             jne   vmm_bad
  2551.  
  2552.             push  cs                ; ds = cs
  2553.             pop   ds
  2554.  
  2555.             mov   ah, 3Ch           ; create the temp file
  2556.             xor   cx, cx
  2557.             lea   dx, [di+6]
  2558.             int   21h
  2559.             jc    vmm_done
  2560.  
  2561.             mov   [di+4], ax        ; save file handle
  2562.  
  2563.             mov   ax, 4300h         ; check for xms
  2564.             int   2Fh
  2565.             test  al, al
  2566.             jz    vmm_noxms
  2567.  
  2568.             mov   al, 10h           ; get xms call point
  2569.             int   2Fh
  2570.             mov   [di], bx
  2571.             mov   [di+2], es
  2572.  
  2573.             mov   ah, 8             ; get free xms size
  2574.             call  [dword di]
  2575.             test  ax, ax            ; no xms memory free?
  2576.             jz    vmm_noxms
  2577.  
  2578.             push  ax
  2579.             xchg  dx, ax            ; allocate all xms
  2580.             mov   ah, 9
  2581.             call  [dword di]
  2582.             test  ax, ax            ; didn't work?
  2583.             jz    vmm_noxms
  2584.  
  2585.             xor   ebx,ebx           ; ebx = xms size
  2586.             pop   bx
  2587.             shl   ebx, 10
  2588.             mov   [di-4], ebx       ; save xms size
  2589.             mov   [di-6], dx        ; save xms handle
  2590.             jmp   vmm_done          ; return
  2591.  
  2592. vmm_noxms:  xor   eax, eax          ; set xms size 0
  2593.             mov   [di-4], eax
  2594.             jmp   vmm_done
  2595.  
  2596. vmm_bad:    stc                     ; invalid request
  2597.             jmp   vmm_done
  2598.  
  2599. vmm_cont:   cmp   ah, 4             ; service out of range?
  2600.             jae   vmm_bad
  2601.  
  2602.             cmp   [word cs:di+4], 0 ; not initialized yet?
  2603.             je    vmm_bad
  2604.  
  2605.             cmp   ah, 1             ; check service number
  2606.             jne   vmm_rw  
  2607.  
  2608.             push  cs                ; ds = cs
  2609.             pop   ds
  2610.  
  2611.             xor   eax, eax          ; clear the handle
  2612.             mov   [di+4], ax
  2613.             cmp   [di-4], eax       ; check for xms
  2614.             je    vmm_skip
  2615.  
  2616.             mov   ah, 10            ; free xms block
  2617.             mov   dx, [di-6]
  2618.             call  [dword di]
  2619.  
  2620. vmm_skip:   mov   ah, 3Eh           ; close temp file
  2621.             mov   bx, [di+4]
  2622.             int   21h
  2623.  
  2624.             mov   ah, 41h           ; delete temp file
  2625.             lea   dx, [di+6]
  2626.             int   21h
  2627.  
  2628. vmm_done:   pop   es ds             ; restore registers
  2629.             popad
  2630.             ret                     ; return
  2631.  
  2632. vmm_rw:     test  ebx, 0F0000001h   ; offset and length must be
  2633.             jnz   vmm_bad           ; even for read/write, also
  2634.             test  cl, 1             ; the length can't be zero.
  2635.             jnz   vmm_bad
  2636.             test  cx, cx
  2637.             jz    vmm_bad
  2638.  
  2639.             mov   ebp, [cs:di-4]    ; ebp = xms length
  2640.             movzx ecx, cx           ; ecx = end offset
  2641.             add   ecx, ebx
  2642.  
  2643.             cmp   ebx, ebp          ; check for xms part
  2644.             jae   vmm_file
  2645.  
  2646.             pushad                  ; save all registers
  2647.             push  ds
  2648.  
  2649.             cmp   ecx, ebp          ; partly in file?
  2650.             jb    $+5
  2651.             mov   ecx, ebp
  2652.  
  2653.             sub   ecx, ebx          ; ecx = length, si = block
  2654.             pusha                   ; get 16 bytes space
  2655.             mov   si, sp
  2656.             push  ss
  2657.  
  2658.             cmp   ah, 2             ; check service number
  2659.             jne   vmm_write
  2660.  
  2661.             mov   [ss:si+14], ds    ; set segment, ds = ss
  2662.             pop   ds
  2663.  
  2664.             mov   ax, [di-6]        ; set xms handle
  2665.             mov   [si+4], ax
  2666.             mov   [si+6], ebx       ; set xms offset
  2667.             mov   [word si+10], 0
  2668.             mov   [si+12], dx       ; set buffer offset
  2669.                   
  2670.             jmp   vmm_xcont         ; jump to continue
  2671.  
  2672. vmm_write:  mov   [ss:si+8], ds     ; set segment, ds = cs
  2673.             pop   ds
  2674.  
  2675.             mov   ax, [di-6]        ; set xms handle
  2676.             mov   [si+10], ax
  2677.             mov   [si+12], ebx      ; set xms offset
  2678.             mov   [word si+4], 0
  2679.             mov   [si+6], dx        ; set buffer offset
  2680.  
  2681. vmm_xcont:  mov   [si], ecx         ; set length
  2682.             mov   ah, 11            ; do it
  2683.             call  [dword cs:di]
  2684.             add   sp, 16            ; release the block
  2685.             cmp   al, 1             ; check return value
  2686.  
  2687.             pop   ds                ; restore registers
  2688.             popad
  2689.  
  2690.             jc    vmm_jdone         ; jump if error
  2691.  
  2692. vmm_file:   sub   ecx, ebp          ; no file part?
  2693.             cmc
  2694.             jnc   vmm_jdone
  2695.  
  2696.             sub   ebx, ebp          ; ebx = start in file
  2697.             jge   $+5
  2698.             xor   ebx, ebx
  2699.  
  2700.             xchg  bp, ax            ; save service number
  2701.  
  2702.             sub   ecx, ebx          ; ecx = length
  2703.             push  cx dx
  2704.  
  2705.             mov   dx, bx            ; cx:dx = offset
  2706.             shr   ebx, 16
  2707.             mov   cx, bx
  2708.  
  2709.             mov   ax, 4200h         ; seek to position
  2710.             mov   bx, [cs:di+4]
  2711.             int   21h
  2712.             pop   dx cx
  2713.  
  2714.             jc    vmm_jdone         ; jump if error
  2715.  
  2716.             xchg  bp, ax            ; ah = service
  2717.             add   ah, 3Dh
  2718.             int   21h               ; read/write file data
  2719. vmm_jdone:  jmp   vmm_done          ; return
  2720.  
  2721. EndP        VMproc
  2722.  
  2723. End
  2724.